<template>
  <div class="video-test">
    <h2>视频测试页面</h2>
    <div class="upload-container">
      <input type="file" @change="handleVideoUpload" accept="video/*" />
      <div class="preview" v-if="videoPreviewUrl">
        <img :src="videoPreviewUrl" alt="视频预览" />
        <div class="download-buttons">
          <button class="download-btn" @click="downloadOriginal">
            <span class="download-icon">↓</span>下载原图
          </button>
          <button class="download-btn" @click="downloadCropped">
            <span class="download-icon">↓</span>下载裁剪图
          </button>
        </div>
      </div>
    </div>
    <router-link to="/" class="back-link">返回首页</router-link>

    <!-- 替换原来的弹窗为 Element Plus 的弹窗 -->
    <el-dialog
      v-model="showModal"
      title="请选择封面区域"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      width="90%"
      @close="closeModal"
    >
      <!-- 时间选择器 -->
      <div class="time-selector">
        <span>当前时间: {{ formatTime(currentTime) }}</span>
        <input 
          type="range" 
          v-model="currentTime" 
          :max="duration" 
          step="0.1" 
          class="time-slider"
          @input="handleTimeChange"
        >
        <span>总时长: {{ formatTime(duration) }}</span>
      </div>

      <div class="zoom-controls">
        <button class="zoom-btn" @click="zoomIn">
          <span class="zoom-icon">+</span>放大
        </button>
        <button class="zoom-btn" @click="zoomOut">
          <span class="zoom-icon">-</span>缩小
        </button>
        <button class="zoom-btn" @click="resetCrop">
          <span class="zoom-icon">↺</span>重置
        </button>
      </div>

      <div class="crop-container" ref="cropContainer">
        <img :src="originalVideoUrl" ref="cropImage" @load="initCrop" />
      </div>

      <div class="size-buttons">
        <button 
          v-for="size in sizeOptions" 
          :key="size.scale"
          :class="['size-btn', { active: currentScale === size.scale }]"
          @click="changeSize(size.scale)"
        >
          {{ size.label }}
        </button>
      </div>

      <div class="crop-info" v-if="cropInfo">
        原图尺寸: {{ originalSize }}，
        截取尺寸: {{ cropInfo.currentSize }} <br>
        <div class="quality-control">
          <el-slider v-model="quality" />
          <span>清晰度: {{ quality }}%</span>
        </div>
      </div>

      <template #footer>
        <span class="dialog-footer">
          <el-button @click="closeModal">取消</el-button>
          <el-button type="primary" @click="handleCrop">确认</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, nextTick } from 'vue'
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.css'

const videoPreviewUrl = ref('')
const originalVideoUrl = ref('')
const showModal = ref(false)
const cropImage = ref(null)
const cropper = ref(null)
const cropInfo = ref(null)
const currentScale = ref(1)
const originalSize = ref('')
const quality = ref(50) // 默认压缩比例为50%
const currentTime = ref(0)
const duration = ref(0)
const videoElement = ref(null)

// 添加 timeoutId 变量
let timeoutId = null

const sizeOptions = [
  { scale: 1, label: '1倍(56×70)', width: 56, height: 70 },
  { scale: 1.5, label: '1.5倍 (84×105)', width: 84, height: 105 },
  { scale: 2, label: '2倍 (112×140)', width: 112, height: 140 },
  { scale: 3, label: '3倍 (168×210)', width: 168, height: 210 },
  { scale: 4, label: '4倍 (224×280)', width: 224, height: 280 },
  { scale: 5, label: '5倍 (280×350)', width: 280, height: 350 },
  { scale: 6, label: '6倍 (336×420)', width: 336, height: 420 },
  { scale: 'fit', label: '适应', width: 56, height: 70 }
]

const formatTime = (time) => {
  const minutes = Math.floor(time / 60)
  const seconds = Math.floor(time % 60)
  const milliseconds = Math.floor((time % 1) * 10)
  return `${minutes}:${seconds.toString().padStart(2, '0')}.${milliseconds}`
}

const handleVideoUpload = (event) => {
  const file = event.target.files[0]
  if (!file) return

  // 释放之前的视频资源
  if (videoElement.value) {
    URL.revokeObjectURL(videoElement.value.src)
  }

  const video = document.createElement('video')
  video.preload = 'auto'  // 改为 auto
  
  const objectUrl = URL.createObjectURL(file)
  video.src = objectUrl
  videoElement.value = video

  video.onloadedmetadata = () => {
    duration.value = video.duration
    currentTime.value = 0
  }

  video.oncanplay = () => {
    captureVideoFrame()
  }
}

const captureVideoFrame = async () => {
  if (!videoElement.value) return
  
  const video = videoElement.value
  
  try {
    video.currentTime = currentTime.value
    await new Promise(resolve => {
      const onSeeked = () => {
        video.removeEventListener('seeked', onSeeked)
        resolve()
      }
      video.addEventListener('seeked', onSeeked)
    })

    const canvas = document.createElement('canvas')
    // 使用视频的原始分辨率
    canvas.width = video.videoWidth
    canvas.height = video.videoHeight
    
    const ctx = canvas.getContext('2d')
    ctx.imageSmoothingEnabled = true
    ctx.imageSmoothingQuality = 'high'
    ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
    
    originalSize.value = `${canvas.width} × ${canvas.height}`
    const newImageUrl = canvas.toDataURL('image/jpeg', 1.0)
    
    // 只在首次捕获时显示弹框
    if (!videoPreviewUrl.value) {
      originalVideoUrl.value = newImageUrl
      showCropModal()
    }
  } catch (error) {
    console.error('捕获视频帧失败:', error)
  }
}

// 添加防抖函数
const debounce = (fn, delay) => {
  let timer = null
  return function (...args) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this, args)
    }, delay)
  }
}

// 修改 handleTimeChange 函数
const handleTimeChange = debounce(async () => {
  if (!showModal.value || !videoElement.value) return

  try {
    const video = videoElement.value

    // 更新视频时间
    video.currentTime = currentTime.value
    
    // 等待视频帧准备好
    await new Promise(resolve => {
      const onSeeked = () => {
        video.removeEventListener('seeked', onSeeked)
        resolve()
      }
      video.addEventListener('seeked', onSeeked)
    })

    // 创建新帧
    const canvas = document.createElement('canvas')
    canvas.width = video.videoWidth
    canvas.height = video.videoHeight
    const ctx = canvas.getContext('2d')
    ctx.drawImage(video, 0, 0, canvas.width, canvas.height)

    // 更新图片源
    originalVideoUrl.value = canvas.toDataURL('image/jpeg', 1.0)

  } catch (error) {
    console.error('更新帧失败:', error)
  }
}, 200)

// 修改 calculateFitSize 函数
const calculateFitSize = (containerData, imageData) => {
  const targetRatio = 56 / 70
  const imageHeight = imageData.naturalHeight
  const imageWidth = imageData.naturalWidth
  
  // 始终使用原图高度，并按比例计算宽度
  const actualHeight = imageHeight
  const actualWidth = Math.round(imageHeight * targetRatio)
  
  // 计算显示比例
  const displayScale = Math.min(
    containerData.width / imageData.naturalWidth,
    containerData.height / imageData.naturalHeight
  )
  
  // 转换为显示尺寸
  const displayWidth = Math.round(actualWidth * displayScale)
  const displayHeight = Math.round(actualHeight * displayScale)

  return { 
    width: displayWidth, 
    height: displayHeight,
    actualWidth,
    actualHeight,
    displayScale
  }
}

// 修改 initCrop 函数
const initCrop = () => {
  const image = cropImage.value
  if (!image) return

  // 确保销毁之前的实例
  if (cropper.value) {
    cropper.value.destroy()
    cropper.value = null
  }

  // 创建新的 cropper 实例
  cropper.value = new Cropper(image, {
    aspectRatio: 56/70,
    viewMode: 2,
    dragMode: 'move',
    autoCropArea: 1,
    minContainerWidth: 400,
    minContainerHeight: 500,
    minCropBoxWidth: 56,
    minCropBoxHeight: 70,
    background: true,
    modal: true,
    highlight: true,
    zoomOnTouch: true,
    zoomOnWheel: true,
    wheelZoomRatio: 0.1,
    cropBoxMovable: true,
    cropBoxResizable: true,
    toggleDragModeOnDblclick: false,
    ready() {
      const containerData = cropper.value.getContainerData()
      const imageData = cropper.value.getImageData()
      
      // 计算适应尺寸
      const { width, height } = calculateFitSize(containerData, imageData)
      
      // 设置裁剪框位置（居中）
      const left = (containerData.width - width) / 2
      const top = (containerData.height - height) / 2
      
      cropper.value.setCropBoxData({
        left,
        top,
        width,
        height
      })

      // 更新裁剪信息
      updateCropInfo(width, height)
    },
    crop(event) {
      // 移除 crop 事件中的尺寸更新
      // if (event && event.detail) {
      //   const cropBoxData = cropper.value.getCropBoxData()
      //   updateCropInfo(cropBoxData.width, cropBoxData.height)
      // }
    }
  })
}

// 修改 showCropModal 函数
const showCropModal = () => {
  currentScale.value = 'fit'
  showModal.value = true
}

// 修改 handleCrop 函数
const handleCrop = () => {
  if (!cropper.value) return

  try {
    const size = sizeOptions.find(s => s.scale === currentScale.value)
    if (!size) return

    // 获取目标尺寸
    let targetWidth, targetHeight
    if (size.scale === 'fit') {
      const [width, height] = cropInfo.value.currentSize.split('×').map(s => parseInt(s.trim()))
      targetWidth = width
      targetHeight = height
    } else {
      targetWidth = size.width
      targetHeight = size.height
    }

    // 获取裁剪数据
    const cropData = cropper.value.getData(true)
    const imageData = cropper.value.getImageData()

    // 计算实际裁剪区域的分辨率
    const sourceWidth = cropData.width
    const sourceHeight = cropData.height

    // 创建临时画布，使用更高的分辨率
    const tempCanvas = document.createElement('canvas')
    tempCanvas.width = sourceWidth
    tempCanvas.height = sourceHeight

    // 先裁剪到临时画布，保持原始分辨率
    const tempCtx = tempCanvas.getContext('2d')
    const sourceCanvas = cropper.value.getCroppedCanvas({
      width: sourceWidth,
      height: sourceHeight,
      imageSmoothingQuality: 'high',
      imageSmoothingEnabled: true
    })
    tempCtx.drawImage(sourceCanvas, 0, 0)

    // 创建最终画布
    const finalCanvas = document.createElement('canvas')
    finalCanvas.width = targetWidth
    finalCanvas.height = targetHeight

    // 将临时画布的内容缩放到最终尺寸
    const finalCtx = finalCanvas.getContext('2d')
    finalCtx.imageSmoothingEnabled = true
    finalCtx.imageSmoothingQuality = 'high'
    finalCtx.drawImage(tempCanvas, 0, 0, targetWidth, targetHeight)

    // 使用更高的质量设置
    const finalBase64 = finalCanvas.toDataURL('image/jpeg', Math.max(quality.value / 100, 0.9))
    
    // 更新预览
    videoPreviewUrl.value = finalBase64
    cropInfo.value = {
      currentSize: `${targetWidth} × ${targetHeight}`,
      fileSize: getBase64Size(finalBase64.split(',')[1])
    }

    if (cropper.value) {
      cropper.value.destroy()
      cropper.value = null
    }

    showModal.value = false
    originalVideoUrl.value = ''
  } catch (error) {
    console.error('裁剪失败:', error)
  }
}

// 修改 closeModal 函数
const closeModal = () => {
  // 销毁 cropper
  if (cropper.value) {
    cropper.value.destroy()
    cropper.value = null
  }
  
  // 关闭弹框
  showModal.value = false
}

// 修改 changeSize 函数
const changeSize = (scale) => {
  currentScale.value = scale
  if (!cropper.value) return

  const containerData = cropper.value.getContainerData()
  const imageData = cropper.value.getImageData()
  
  // 计算图片在容器中的显示比例
  const displayScale = Math.min(
    containerData.width / imageData.naturalWidth,
    containerData.height / imageData.naturalHeight
  )

  let displayWidth, displayHeight, actualWidth, actualHeight
  
  if (scale === 'fit') {
    const fitSize = calculateFitSize(containerData, imageData)
    displayWidth = fitSize.width
    displayHeight = fitSize.height
    actualWidth = fitSize.actualWidth
    actualHeight = fitSize.actualHeight
    
    // 更新裁剪信息
    cropInfo.value = {
      currentSize: `${actualWidth} × ${actualHeight}`,
      targetSize: '适应原图最大尺寸'
    }
  } else {
    const size = sizeOptions.find(s => s.scale === scale)
    if (!size) return
    
    // 检查是否超出原图尺寸
    if (size.height > imageData.naturalHeight) {
      // 如果高度超出，则按原图高度计算
      actualHeight = imageData.naturalHeight
      actualWidth = Math.round(actualHeight * (56/70))
    } else {
      actualWidth = size.width
      actualHeight = size.height
    }
    
    // 计算显示尺寸时保持原始比例
    displayWidth = Math.round(actualWidth * displayScale)
    displayHeight = Math.round(actualHeight * displayScale)
    
    // 更新裁剪信息
    cropInfo.value = {
      currentSize: `${actualWidth} × ${actualHeight}`,
      targetSize: size.height > imageData.naturalHeight ? '(已按原图高度自动调整)' : ''
    }
  }

  // 获取当前裁剪框中心点
  const cropBoxData = cropper.value.getCropBoxData()
  const centerX = cropBoxData.left + (cropBoxData.width / 2)
  const centerY = cropBoxData.top + (cropBoxData.height / 2)

  // 设置新的裁剪框位置
  cropper.value.setCropBoxData({
    left: Math.max(0, centerX - (displayWidth / 2)),
    top: Math.max(0, centerY - (displayHeight / 2)),
    width: displayWidth,
    height: displayHeight
  })
}

const zoomIn = () => {
  if (cropper.value) {
    cropper.value.zoom(0.1)
  }
}

const zoomOut = () => {
  if (cropper.value) {
    cropper.value.zoom(-0.1)
  }
}

const resetCrop = () => {
  if (cropper.value) {
    cropper.value.reset()
    currentScale.value = 'fit'
  }
}

// 添加文件大小计算函数
const getBase64Size = (base64String) => {
  const padding = base64String.endsWith('==') ? 2 : base64String.endsWith('=') ? 1 : 0
  const base64Length = base64String.length
  const bytes = Math.floor(((base64Length * 0.75) - padding))
  
  if (bytes < 1024) return bytes + ' B'
  else if (bytes < 1048576) return (bytes / 1024).toFixed(2) + ' KB'
  else return (bytes / 1048576).toFixed(2) + ' MB'
}

const downloadImage = (dataUrl, fileName) => {
  const link = document.createElement('a')
  link.href = dataUrl
  link.download = fileName
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

const downloadOriginal = () => {
  if (originalVideoUrl.value) {
    downloadImage(originalVideoUrl.value, 'original.jpg')
  }
}

const downloadCropped = () => {
  if (videoPreviewUrl.value) {
    downloadImage(videoPreviewUrl.value, `cropped_q${quality.value}.jpg`)
  }
}

// 修改 updateCropInfo 函数
const updateCropInfo = (width, height) => {
  if (!cropper.value) return
  
  // 如果是固定尺寸，保持当前尺寸
  if (currentScale.value !== 'fit') {
    return
  }
  
  // 对于适应尺寸，使用原图高度
  const imageData = cropper.value.getImageData()
  const actualHeight = imageData.naturalHeight
  const actualWidth = Math.round(actualHeight * (56/70))
  
  cropInfo.value = {
    currentSize: `${actualWidth} × ${actualHeight}`,
    targetSize: '适应原图最大尺寸'
  }
}
</script>

<style scoped>
.video-test {
  padding: 20px;
  text-align: center;
}

.upload-container {
  margin: 20px 0;
}

.preview {
  margin-top: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.preview img {
  max-width: 100%;
  max-height: 500px;
  margin-bottom: 10px;
}

.back-link {
  display: inline-block;
  margin-top: 20px;
  padding: 10px 20px;
  background-color: #666;
  color: white;
  text-decoration: none;
  border-radius: 4px;
}

.back-link:hover {
  background-color: #555;
}

.size-buttons {
  margin: 20px 0;
  display: flex;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
  max-width: 800px;
  margin-left: auto;
  margin-right: auto;
}

.size-btn {
  padding: 6px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  background-color: white;
  cursor: pointer;
  transition: all 0.3s;
  font-size: 14px;
}

.size-btn:hover {
  background-color: #f0f0f0;
}

.size-btn.active {
  background-color: #4CAF50;
  color: white;
  border-color: #4CAF50;
}

/* 为适应按钮添加特殊样式 */
.size-btn:last-child {
  /* 使用与其他按钮相同的样式 */
  background-color: white;
  color: inherit;
  border-color: #ddd;
}

.size-btn:last-child:hover {
  background-color: #f0f0f0;
}

.size-btn:last-child.active {
  background-color: #4CAF50;
  color: white;
  border-color: #4CAF50;
}

.modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  max-width: 90%;
  max-height: 90vh; /* 使用视口高度单位 */
  overflow: auto;
}

.zoom-controls {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin: 10px 0;
}

.zoom-btn {
  display: flex;
  align-items: center;
  padding: 6px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  background-color: white;
  cursor: pointer;
  transition: all 0.3s;
  font-size: 14px;
  min-width: 80px; /* 确保按钮宽度一致 */
  justify-content: center; /* 居中按钮内容 */
}

.zoom-btn:hover {
  background-color: #f0f0f0;
}

.zoom-icon {
  font-weight: bold;
  margin-right: 4px;
  font-size: 16px;
}

.crop-container {
  max-width: 800px;
  max-height: 600px;
  margin: 10px auto;
  overflow: hidden;
  background-color: #f5f5f5;
}

.crop-container img {
  max-width: 100%;
}

.modal-buttons {
  margin-top: 20px;
}

.confirm-btn, .cancel-btn {
  padding: 8px 20px;
  margin: 0 10px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.confirm-btn {
  background-color: #4CAF50;
  color: white;
}

.confirm-btn:hover {
  background-color: #45a049;
}

.cancel-btn {
  background-color: #666;
  color: white;
}

.cancel-btn:hover {
  background-color: #555;
}

.crop-info {
  margin: 10px 0;
  color: #666;
  font-size: 14px;
  line-height: 1.8; /* 增加行间距 */
}

/* 为重置按钮添加特殊的 hover 效果 */
.zoom-btn:last-child:hover {
  background-color: #f0f0f0;
  color: #666;
}

.download-buttons {
  margin-top: 15px;
  display: flex;
  justify-content: center;
  gap: 10px;
}

.download-btn {
  display: flex;
  align-items: center;
  padding: 8px 16px;
  border: 1px solid #4CAF50;
  border-radius: 4px;
  background-color: white;
  color: #4CAF50;
  cursor: pointer;
  transition: all 0.3s;
  font-size: 14px;
}

.download-btn:hover {
  background-color: #4CAF50;
  color: white;
}

.download-icon {
  font-weight: bold;
  margin-right: 6px;
  font-size: 16px;
}

.quality-control {
  width: 300px;
  display: flex;
  /* flex-direction: column; */
  align-items: center;
  gap: 5px;
  margin: 10px auto;
}

.quality-control span {
  font-size: 14px;
  color: #666;
  white-space: nowrap;
  margin-left: 10px;
}

.quality-slider {
  width: 200px;
  height: 4px;
  -webkit-appearance: none;
  background: #ddd;
  outline: none;
  border-radius: 2px;
  cursor: pointer;
}

.quality-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  background: #4CAF50;
  border-radius: 50%;
  cursor: pointer;
  transition: background-color 0.3s;
}

.quality-slider::-moz-range-thumb {
  width: 16px;
  height: 16px;
  background: #4CAF50;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  transition: background-color 0.3s;
}

.quality-slider::-webkit-slider-thumb:hover {
  background: #45a049;
}

.quality-slider::-moz-range-thumb:hover {
  background: #45a049;
}

/* 优化滑块轨道样式 */
.quality-slider::-webkit-slider-runnable-track {
  height: 4px;
  background: #ddd;
  border-radius: 2px;
}

.quality-slider::-moz-range-track {
  height: 4px;
  background: #ddd;
  border-radius: 2px;
}

.page-selector {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin: 10px 0;
}

.page-selector select {
  padding: 6px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 14px;
  cursor: pointer;
  outline: none;
  background-color: white;
}

.page-selector select:hover {
  border-color: #4CAF50;
}

.page-selector select:focus {
  border-color: #4CAF50;
  box-shadow: 0 0 0 2px rgba(74, 175, 80, 0.2);
}

.total-pages {
  color: #666;
  font-size: 14px;
}

/* 添加一些 Element Plus 弹窗相关的样式 */
.el-dialog {
  display: flex;
  flex-direction: column;
  margin: 0 !important;
  max-height: 90vh;
  overflow: hidden;
}

.el-dialog__body {
  flex: 1;
  overflow: auto;
  padding: 20px;
}

.dialog-footer {
  padding: 20px;
  text-align: right;
}
</style> 